package org.tinygroup.tinytest;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.SmartContextLoader;
import org.springframework.test.context.support.AbstractDelegatingSmartContextLoader;
import org.tinygroup.beancontainer.BeanContainerFactory;
import org.tinygroup.springutil.ExtendsSpringBeanContainer;

/**
 * 重写loadContext方法，捕捉IllegalStateException，返回GenericApplicationContext实例
 * 
 * @author renhui
 *
 */
public class TinyDelegatingSmartContextLoader extends
		AbstractDelegatingSmartContextLoader {

	private final SmartContextLoader smartContextLoader;

	public TinyDelegatingSmartContextLoader(
			SmartContextLoader smartContextLoader) {
		super();
		this.smartContextLoader = smartContextLoader;
	}

	@Override
	public ApplicationContext loadContext(
			MergedContextConfiguration mergedConfig) throws Exception {

		try {
			AbstractApplicationContext applicationContext = (AbstractApplicationContext) smartContextLoader
					.loadContext(mergedConfig);
			ExtendsSpringBeanContainer beanContainer = (ExtendsSpringBeanContainer) BeanContainerFactory
					.getBeanContainer(getClass().getClassLoader());
			AbstractApplicationContext parentContext = (AbstractApplicationContext) beanContainer
					.getBeanContainerPrototype();
			addBeanFactoryPostProcessors(applicationContext, parentContext);
			addBeanPostProcessors(applicationContext, parentContext);
			return applicationContext;
		} catch (IllegalStateException e) {
			ExtendsSpringBeanContainer beanContainer = (ExtendsSpringBeanContainer) BeanContainerFactory
					.getBeanContainer(getClass().getClassLoader());
			return beanContainer.getBeanContainerPrototype();
		}
	}

	private void addBeanPostProcessors(
			AbstractApplicationContext applicationContext,
			ApplicationContext parentContext) {
		DefaultListableBeanFactory parentListableBeanFactory = (DefaultListableBeanFactory) parentContext
				.getAutowireCapableBeanFactory();
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext
				.getAutowireCapableBeanFactory();
		for (BeanPostProcessor beanPostProcessor : parentListableBeanFactory
				.getBeanPostProcessors()) {
			defaultListableBeanFactory.addBeanPostProcessor(beanPostProcessor);
		}
	}

	private void addBeanFactoryPostProcessors(
			AbstractApplicationContext applicationContext,
			AbstractApplicationContext parentContext) {
		for (BeanFactoryPostProcessor beanFactoryPostProcessor : parentContext
				.getBeanFactoryPostProcessors()) {
			applicationContext
					.addBeanFactoryPostProcessor(beanFactoryPostProcessor);
		}
		String[] postProcessorNames = applicationContext.getBeanNamesForType(
				BeanFactoryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			applicationContext.addBeanFactoryPostProcessor(parentContext
					.getBean(ppName, BeanFactoryPostProcessor.class));
		}
	}

	@Override
	protected SmartContextLoader getXmlLoader() {
		return null;
	}

	@Override
	protected SmartContextLoader getAnnotationConfigLoader() {
		return null;
	}

}
